VintaSoft Imaging .NET SDK 15.1: Documentation for .NET developer
Vintasoft.Imaging.Pdf Namespace / PdfFontManager Class / CreateFontSubset Methods / CreateFontSubset(PdfFont,PdfTextSymbol[],Int32,Boolean,PdfTextSymbol[]) Method
Syntax Exceptions Example Requirements SeeAlso
In This Topic
CreateFontSubset(PdfFont,PdfTextSymbol[],Int32,Boolean,PdfTextSymbol[]) Method (PdfFontManager)
In This Topic
Creates new PDF font, which contains the specified set of text symbols.
Syntax
'Declaration

Public Overloads Function CreateFontSubset( _
ByVal sourceFont
Source PDF font.
As Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont, _
ByVal symbols
A set of text symbols from source PDF font. Text symbols are ordered as they should be stored in new PDF font.
() As Vintasoft.Imaging.Pdf.Content.TextExtraction.PdfTextSymbol, _
ByVal symbolCodeSize
Size, in bytes, of code symbol of new PDF font.
As System.Int32, _
ByVal addEncoding
A value indicating whether the information about Unicode codes of symbols must be added to new PDF font.
As Boolean, _
ByRef newSymbols
An array of text symbols of newly created PDF font. Each symbol in array newSymbols corresponds to the symbol, with the same index, in array symbols.
() As Vintasoft.Imaging.Pdf.Content.TextExtraction.PdfTextSymbol _
) As Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont

Parameters

sourceFont
Source PDF font.
symbols
A set of text symbols from source PDF font. Text symbols are ordered as they should be stored in new PDF font.
symbolCodeSize
Size, in bytes, of code symbol of new PDF font.
addEncoding
A value indicating whether the information about Unicode codes of symbols must be added to new PDF font.
newSymbols
An array of text symbols of newly created PDF font. Each symbol in array newSymbols corresponds to the symbol, with the same index, in array symbols.

Return Value

New PDF font.
Exceptions
ExceptionDescription
Thrown if sourceFont or symbols is null.
Thrown if array of symbols is empty -or- original font is not fully defined.
Thrown if array of symbols contains symbols from another font.
Thrown if symbolCodeSize is 0 or exceeds 2 -or- number of symbols exceeds maximum number that can be encoded by symbolCodeSize.
Thrown if subsetting of sourceFont is not supported.
Example

Here is an example that shows how to create a PDF font, which is based on a subset of font symbols:


''' <summary>
''' Creates CID font, which is based on the specified TrueType font,
''' creates a PDF font, which is a minimal subset necessary for drawing specified text, and
''' creates a PDF document with the specified text and font.
''' </summary>
''' <param name="pdfFilename">The name of file, where PDF document must be saved.</param>
''' <param name="trueTypeFontFilename">The filename of TrueType font.</param>
''' <param name="text">The text to draw on PDF page.</param>
Public Shared Sub CreatePdfFontSubset(pdfFilename As String, trueTypeFontFilename As String, text As String)
    ' list of unique necessary characters to render specified text
    Dim usedChars As New System.Collections.Generic.List(Of Char)()
    For i As Integer = 0 To text.Length - 1
        If Not usedChars.Contains(text(i)) Then
            usedChars.Add(text(i))
        End If
    Next

    ' create new PDF document
    Using document As New Vintasoft.Imaging.Pdf.PdfDocument()
        ' create initial PDF font
        Dim sourceFont As Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont = document.FontManager.CreateCIDFontFromTrueTypeFont(trueTypeFontFilename)
        ' get symbols of the font
        Dim fontSymbols As Vintasoft.Imaging.Pdf.Content.TextExtraction.PdfTextSymbol() = Vintasoft.Imaging.Pdf.Content.TextExtraction.PdfTextSymbol.GetFontSymbols(sourceFont)
        ' list of PDF font symbols, which are necessary for rendering the specified text
        Dim necessarySymbols As New System.Collections.Generic.List(Of Vintasoft.Imaging.Pdf.Content.TextExtraction.PdfTextSymbol)()
        For i As Integer = 0 To fontSymbols.Length - 1
            ' get next PDF font symbol
            Dim fontSymbol As Vintasoft.Imaging.Pdf.Content.TextExtraction.PdfTextSymbol = fontSymbols(i)
            ' determine if symbol is used in text
            For j As Integer = 0 To usedChars.Count - 1
                If fontSymbol.Symbol = usedChars(j) Then
                    necessarySymbols.Add(fontSymbol)
                    Exit For
                End If
            Next

            If necessarySymbols.Count = usedChars.Count Then
                ' optimization: we have all necessary symbols and can go on
                Exit For
            End If
        Next

        ' determine symbol code size in bytes
        Dim symbolCodeSizeInBytes As Integer = If(sourceFont.FontType = Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFontType.Type0, 2, 1)
        Dim newSymbols As Vintasoft.Imaging.Pdf.Content.TextExtraction.PdfTextSymbol() = Nothing
        ' create font subset
        Dim pdfFontSubset As Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont = document.FontManager.CreateFontSubset(sourceFont, necessarySymbols.ToArray(), symbolCodeSizeInBytes, True, newSymbols)

        ' add PDF page
        Dim page As Vintasoft.Imaging.Pdf.Tree.PdfPage = document.Pages.Add(Vintasoft.Imaging.PaperSizeKind.A4)
        ' open PDF graphics
        Using graphics As Vintasoft.Imaging.Pdf.Drawing.PdfGraphics = page.GetGraphics()
            Dim brush As New Vintasoft.Imaging.Pdf.Drawing.PdfBrush(System.Drawing.Color.Black)
            Dim location As New System.Drawing.PointF(30, page.Size.Height - 150)
            ' draw text using created font
            graphics.DrawString(text, pdfFontSubset, 18F, brush, location)
        End Using
        ' pack PDF document to the specified location
        document.Pack(pdfFilename)
    End Using
End Sub


/// <summary>
/// Creates CID font, which is based on the specified TrueType font,
/// creates a PDF font, which is a minimal subset necessary for drawing specified text, and
/// creates a PDF document with the specified text and font.
/// </summary>
/// <param name="pdfFilename">The name of file, where PDF document must be saved.</param>
/// <param name="trueTypeFontFilename">The filename of TrueType font.</param>
/// <param name="text">The text to draw on PDF page.</param>
public static void CreatePdfFontSubset(string pdfFilename, string trueTypeFontFilename, string text)
{
    // list of unique necessary characters to render specified text
    System.Collections.Generic.List<char> usedChars = 
        new System.Collections.Generic.List<char>();
    for (int i = 0; i < text.Length; i++)
    {
        if (!usedChars.Contains(text[i]))
            usedChars.Add(text[i]);
    }

    // create new PDF document
    using (Vintasoft.Imaging.Pdf.PdfDocument document = new Vintasoft.Imaging.Pdf.PdfDocument())
    {
        // create initial PDF font
        Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont sourceFont = 
            document.FontManager.CreateCIDFontFromTrueTypeFont(trueTypeFontFilename);
        // get symbols of the font
        Vintasoft.Imaging.Pdf.Content.TextExtraction.PdfTextSymbol[] fontSymbols = 
            Vintasoft.Imaging.Pdf.Content.TextExtraction.PdfTextSymbol.GetFontSymbols(sourceFont);
        // list of PDF font symbols, which are necessary for rendering the specified text
        System.Collections.Generic.List<Vintasoft.Imaging.Pdf.Content.TextExtraction.PdfTextSymbol> necessarySymbols = 
            new System.Collections.Generic.List<Vintasoft.Imaging.Pdf.Content.TextExtraction.PdfTextSymbol>();
        for (int i = 0; i < fontSymbols.Length; i++)
        {
            // get next PDF font symbol
            Vintasoft.Imaging.Pdf.Content.TextExtraction.PdfTextSymbol fontSymbol = fontSymbols[i];
            // determine if symbol is used in text
            for (int j = 0; j < usedChars.Count; j++)
            {
                if (fontSymbol.Symbol == usedChars[j])
                {
                    necessarySymbols.Add(fontSymbol);
                    break;
                }
            }

            if (necessarySymbols.Count == usedChars.Count)
            {
                // optimization: we have all necessary symbols and can go on
                break;
            }
        }

        // determine symbol code size in bytes
        int symbolCodeSizeInBytes = sourceFont.FontType == Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFontType.Type0 ? 2 : 1;
        Vintasoft.Imaging.Pdf.Content.TextExtraction.PdfTextSymbol[] newSymbols = null;
        // create font subset
        Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont pdfFontSubset = document.FontManager.CreateFontSubset(
            sourceFont,
            necessarySymbols.ToArray(),
            symbolCodeSizeInBytes,
            true,
            out newSymbols);

        // add PDF page
        Vintasoft.Imaging.Pdf.Tree.PdfPage page = document.Pages.Add(
            Vintasoft.Imaging.PaperSizeKind.A4);
        // open PDF graphics
        using (Vintasoft.Imaging.Pdf.Drawing.PdfGraphics graphics = page.GetGraphics())
        {
            Vintasoft.Imaging.Pdf.Drawing.PdfBrush brush = 
                new Vintasoft.Imaging.Pdf.Drawing.PdfBrush(System.Drawing.Color.Black);
            System.Drawing.PointF location = new System.Drawing.PointF(30, page.Size.Height - 150);
            // draw text using created font
            graphics.DrawString(text, pdfFontSubset, 18f, brush, location);
        }
        // pack PDF document to the specified location
        document.Pack(pdfFilename);
    }
}

Requirements

Target Platforms: .NET 10; .NET 9; .NET 8; .NET 7; .NET 6; .NET Framework 4.8, 4.7, 4.6, 4.5, 4.0, 3.5

See Also